﻿/*
 * dmsync.cpp
 *
 *  Created on: 2017年4月14日
 *      Author: work
 */

#include <iostream>
#include <boost/program_options.hpp>
#include <dm/os/protocol/protocolcontrolor.hpp>
#include <dm/os/protocol/protocollistenor.hpp>
#include <dm/os/ascom/tcplistner.hpp>
#include <dm/os/ascom/tcpclientdevice.hpp>
#include <dm/os/ascom/serialdevice.hpp>
#include <dm/os/ascom/timer.hpp>
#include <dm/os/com/timer.hpp>
#include <dm/os/msg/msgdriver.hpp>
#include "masterdm.h"
#include "slaverdm.h"
#include <dm/os/sys/taskagent.hpp>

using namespace std;
using namespace boost::program_options;

using namespace dm::os;

int main( int argc,char* argv[] ){
	options_description desc("【DM2016帮助文档】\n DM同步工具。\n\t基于DM2016系统构建\n支持以下选项");

	options_description opts_generic("一般选项");
	opts_generic.add_options()
			("help,h","显示本帮助信息")
			("version,v","显示版本及编译信息")
			("test","测试模式运行")
			;
	desc.add(opts_generic);

	options_description opts_cmd("命令选项");
	opts_cmd.add_options()
					("master,m","做为主站运行。否则作为子站")
					("server,s","作为服务端。否则作为客户端")
					("ip",value<string>(),"ip")
					("port,p",value<int>()->default_value(12404),"端口")
					("serial",value<string>(),"串口通信：/dev/ttyS1:115200:8:1:0:0")
					("refresh,r",value<int>()->default_value(500),"刷新间隔：毫秒")
					("rx-timeout",value<int>()->default_value(30),"接收数据超时时间: 秒")
					("wait",value<int>()->default_value(10),"接收等待超时时间: 秒")
					("con-max",value<unsigned int>()->default_value(0),"允许的最大连接次数。默认无限制")
					("clock",value<int>()->default_value(0),"对时间隔: 秒. 0表示不对时")
					("offset-s",value<int>()->default_value(0),"状态量偏移")
					("offset-d",value<int>()->default_value(0),"离散量偏移")
					("offset-m",value<int>()->default_value(0),"测量量偏移")
					("offset-c",value<int>()->default_value(0),"累计量偏移")
					("offset-r",value<int>()->default_value(0),"远控偏移")
					("offset-p",value<int>()->default_value(0),"参数偏移")
					("offset-a",value<int>()->default_value(0),"动作偏移")
					("size-s",value<int>()->default_value(-1),"状态量数量。-1使用系统配置")
					("size-d",value<int>()->default_value(-1),"离散量数量。-1使用系统配置")
					("size-m",value<int>()->default_value(-1),"测量量数量。-1使用系统配置")
					("size-c",value<int>()->default_value(-1),"累计量数量。-1使用系统配置")
					("size-r",value<int>()->default_value(-1),"远控数量。-1使用系统配置")
					("size-p",value<int>()->default_value(-1),"参数数量。-1使用系统配置")
					("size-a",value<int>()->default_value(-1),"动作数量。-1使用系统配置")
					;
	desc.add(opts_cmd);

	options_description opts_master("作为主站的附加选项选项");
	opts_master.add_options()
		("device,d",value<string>(),"设备名")
		("call-interval,c",value<int>()->default_value(60),"召唤间隔（秒）")
		("tx-interval",value<int>()->default_value(0),"发送间隔（毫秒）")
		("acpt-clk","接受子站对时")
		;

	desc.add(opts_master);

	options_description opts_slaver("作为子站的附加选项选项");
	opts_slaver.add_options()
		("logicdevice,l",value<string>(),"逻辑设备名.为设置则使用全设备")
		("dny-clk","不接受主站对时")
		;

	desc.add(opts_slaver);

	variables_map vm;
	try{
		store(parse_command_line(argc,argv,desc),vm);
		notify(vm);
	}catch( std::exception& ex ){
		cout << ex.what()<<endl;
		return 1;
	}

	if( vm.count("version") ){
		cout <<"V1.0 构建于 "<<__DATE__<<endl;
		return 1;
	}

	if( vm.count("help") ){
		cout <<desc<<endl;
		return 1;
	}

	dm::os::sys::CTaskAgent* taskAgent = NULL;

	if( !vm.count("test") )
		taskAgent = new dm::os::sys::CTaskAgent(argc,argv);

	com::ios_t ios;

	protocol::CProtocolControlor* controlor = new protocol::CProtocolControlor(ios);
	protocol::CProtocolControlor::protocol_t* protocol;

	if( vm.count("master") ){
		CMasterDm* protocolDm = new CMasterDm;
		if( vm.count("device") ){
			if( !protocolDm->setDevice(vm["device"].as<string>().c_str()) ){
				cout <<"不存在设备"<<vm["device"].as<string>()<<endl;
				return -1;
			}
		}

		if( !protocolDm->setStatusOffset(vm["offset-s"].as<int>()) ){
			cout <<"参数--offset-s无效"<<endl;
			return -1;
		}

		if( !protocolDm->setStatusSize( vm["size-s"].as<int>()) ){
			cout <<"参数--size-s无效"<<endl;
			return -1;
		}

		if( !protocolDm->setDiscreteOffset(vm["offset-d"].as<int>()) ){
			cout <<"参数--offset-d无效"<<endl;
			return -1;
		}

		if( !protocolDm->setDiscreteSize(vm["size-d"].as<int>()) ){
			cout <<"参数--size-d无效"<<endl;
			return -1;
		}

		if( !protocolDm->setMeasureOffset(vm["offset-m"].as<int>())){
			cout <<"参数--offset-m无效"<<endl;
			return -1;
		}

		if( !protocolDm->setMeasureSize(vm["size-m"].as<int>()) ){
			cout <<"参数--size-m无效"<<endl;
			return -1;
		}

		if( !protocolDm->setCumulantOffset(vm["offset-c"].as<int>()) ){
			cout <<"参数--offset-c无效"<<endl;
			return -1;
		}

		if( !protocolDm->setCumulantSize(vm["size-c"].as<int>()) ){
			cout <<"参数--size-c无效"<<endl;
			return -1;
		}

		if( !protocolDm->setRmtctlOffset(vm["offset-r"].as<int>()) ){
			cout <<"参数--offset-r无效"<<endl;
			return -1;
		}

		if( !protocolDm->setRmtctlSize(vm["size-r"].as<int>()) ){
			cout <<"参数--size-r无效"<<endl;
			return -1;
		}

		if( !protocolDm->setParameterOffset(vm["offset-p"].as<int>()) ){
			cout <<"参数--offset-p无效"<<endl;
			return -1;
		}

		if( !protocolDm->setParameterSize(vm["size-p"].as<int>()) ){
			cout <<"参数--size-p无效"<<endl;
			return -1;
		}

		if( !protocolDm->setActionOffset(vm["offset-a"].as<int>()) ){
			cout <<"参数--offset-a无效"<<endl;
			return -1;
		}

		if( !protocolDm->setActionSize(vm["size-a"].as<int>()) ){
			cout <<"参数--size-a无效"<<endl;
			return -1;
		}

		protocolDm->setCallInterval(vm["call-interval"].as<int>());
		protocolDm->setWaitTimeout( vm["wait"].as<int>());
		protocolDm->setSendInterval( vm["tx-interval"].as<int>());
		cout <<"设置发送间隔 "<<vm["tx-interval"].as<int>()<<endl;

		protocolDm->setAcceptClock( vm.count("acpt-clk"));

		if( vm.count("clock")  )
			protocolDm->setClockInterval( vm["clock"].as<int>());

		protocol = protocolDm;
	}else{
		CSlaverDm* protocolDm = new CSlaverDm;
		if( vm.count("logicdevice") ){
			if( !protocolDm->setLogicDeviceByName(vm["logicdevice"].as<string>().c_str()) ){
				cout <<"不存在逻辑设备"<<vm["logicdevice"].as<string>()<<endl;
				return -1;
			}
		}

		if( !protocolDm->setStatusOffset(vm["offset-s"].as<int>()) ){
			cout <<"参数--offset-s无效"<<endl;
			return -1;
		}

		if( !protocolDm->setStatusSize( vm["size-s"].as<int>()) ){
			cout <<"参数--size-s无效"<<endl;
			return -1;
		}

		if( !protocolDm->setDiscreteOffset(vm["offset-d"].as<int>()) ){
			cout <<"参数--offset-d无效"<<endl;
			return -1;
		}

		if( !protocolDm->setDiscreteSize(vm["size-d"].as<int>()) ){
			cout <<"参数--size-d无效"<<endl;
			return -1;
		}

		if( !protocolDm->setMeasureOffset(vm["offset-m"].as<int>())){
			cout <<"参数--offset-m无效"<<endl;
			return -1;
		}

		if( !protocolDm->setMeasureSize(vm["size-m"].as<int>()) ){
			cout <<"参数--size-m无效"<<endl;
			return -1;
		}

		if( !protocolDm->setCumulantOffset(vm["offset-c"].as<int>()) ){
			cout <<"参数--offset-c无效"<<endl;
			return -1;
		}

		if( !protocolDm->setCumulantSize(vm["size-c"].as<int>()) ){
			cout <<"参数--size-c无效"<<endl;
			return -1;
		}

		if( !protocolDm->setRmtctlOffset(vm["offset-r"].as<int>()) ){
			cout <<"参数--offset-r无效"<<endl;
			return -1;
		}

		if( !protocolDm->setRmtctlSize(vm["size-r"].as<int>()) ){
			cout <<"参数--size-r无效"<<endl;
			return -1;
		}

		if( !protocolDm->setParameterOffset(vm["offset-p"].as<int>()) ){
			cout <<"参数--offset-p无效"<<endl;
			return -1;
		}

		if( !protocolDm->setParameterSize(vm["size-p"].as<int>()) ){
			cout <<"参数--size-p无效"<<endl;
			return -1;
		}

		if( !protocolDm->setActionOffset(vm["offset-a"].as<int>()) ){
			cout <<"参数--offset-a无效"<<endl;
			return -1;
		}

		if( !protocolDm->setActionSize(vm["size-a"].as<int>()) ){
			cout <<"参数--size-a无效"<<endl;
			return -1;
		}

		protocolDm->setWaitTimeout( vm["wait"].as<int>());
		protocolDm->setAcceptClock(!vm.count("dny-ckl"));
		if( vm.count("clock")  )
			protocolDm->setClockInterval( vm["clock"].as<int>());

		protocol = protocolDm;
	}

	if( vm.count("server") ){
		// 运行在服务端模式
		protocol::CProtocolListenor* listner = new protocol::CProtocolListenor;
		ascom::CTcpListner* port = new ascom::CTcpListner(ios);

		com::CTcpServerAddr address;
		if( vm.count("ip") )
			address.setLocalHost(vm["ip"].as<string>().c_str());
		else
			address.setLocalHost("0.0.0.0");

		address.setLocalPort(vm["port"].as<int>());

		port->setAddress(address);

		listner->setListenor( port );

		controlor->setProtocol(protocol );

		listner->addProtocolControlor(controlor);
		listner->startListen();
	}else if(vm.count("serial")){
		// 运行在串口模式
		com::CSerialAddr address;
		if( !address.fromString(vm["serial"].as<string>().c_str()) ){
			cout <<"请使用--serial设置正确的串口地址"<<endl;
			return 1;
		}

		ascom::CSerialDevice* device = new ascom::CSerialDevice(ios);
		device->setAddress(address);

		controlor->setProtocol(protocol );
		controlor->setDevice(device);
		controlor->setAutoConnect();
		controlor->openDevice();
	}else{
		// 运行在客户端模式
		com::CTcpClientAddr address;

		if( vm.count("ip") )
			address.setServerHost(vm["ip"].as<string>().c_str());
		else{
			cout <<"请指定主机IP"<<endl;
			return 0;
		}

		address.setServerPort( vm["port"].as<int>());

		ascom::CTcpClientDevice* device = new ascom::CTcpClientDevice(ios);
		device->setAddress(address);

		controlor->setProtocol(protocol );
		controlor->setDevice(device);
		controlor->setAutoConnect();
		controlor->openDevice();
	}

	protocol->setRefreshInterval(vm["refresh"].as<int>());
	controlor->setConnectCntMax( vm["con-max"].as<unsigned int>());

	if( taskAgent ){
		dm::os::com::CTimer timer(ios);
		timer.start_seconds(true,10);
		while( taskAgent->runOnce() ){
			ios.run_one();

			if( controlor->isExiting() )
				break;
		}

		delete taskAgent;
	}else{
		ios.run();
	}

	return 0;
}


